package com.simp.run;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.alibaba.fastjson.util.IOUtils;
import com.github.benmanes.caffeine.cache.Cache;
import com.simp.costant.Constant;
import com.simp.process.RunProcess;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.*;
import java.sql.SQLSyntaxErrorException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

/**
 * 初始化加载内容
 *
 * @author pan.shun
 * @since 2022/3/1 15:28
 */
@Component
@Slf4j
public class InitRunProcess extends RunProcess implements CommandLineRunner {

    /**
     * 这个是初始化脚本的名称
     */
    private static final String INIT_DB_FILE_NAME = "hw_cloud.sql";

    @Value("${swagger.enable:true}")
    private boolean swaggerEnable;

    @Value("${server.port}")
    private String port;

    private final Cache<String, Object> caffeineCache;

    @Autowired
    public InitRunProcess(Cache<String, Object> caffeineCache) {
        this.caffeineCache = caffeineCache;
    }

    @Override
    public void run(String... args) {
        if (swaggerEnable) {
            log.info("Swagger 访问地址为 :http://localhost:{}/swagger-ui.html#/", port);
        }
        // 启动时间记录
        recordProjectStartTime();

        printLogo();
    }

    public static void initStartConfig(String[] args) throws Exception {
        log.info("-------------------温馨提示-------------------\r\n");
        log.info("输入java -jar xx.jar start 只生成启动脚本");
        log.info("输入java -jar xx.jar stop  结束当前进程");
        log.info("输入java -jar xx.jar init  加载初始化sql脚本与配置文件");
        log.info("以上的指令可以一起使用，位于前面的优先执行");
        log.info("----------------------------------------------");
        if (check()) {
            // 这个主要是用于初次，方便查看提示信息
            Thread.sleep(3000);
        }
        for (String arg : args) {
            if ("start".equals(arg)) {
                initShellWords("simple-label-core-1.0.jar");
            }
            if ("init".equals(arg)) {
                initMysql();
                createYml();
                log.info("脚本初始化完毕，请完成yml中相关配置");
                System.exit(1);
            }
            if ("stop".equals(arg)) {
                System.exit(1);
            }
        }
    }


    /**
     * 记录最近启动时间
     */
    private void recordProjectStartTime() {
        caffeineCache.put(Constant.CACHE_KEY.PROJECT_START_TIME, System.currentTimeMillis());
    }

    /**
     * 执行初始化脚本
     */
    private static void initMysql() {
        log.info("************开始执行mysql初始化脚本*********");
        log.info("温馨提示：请准备一个空的mysql数据库，以便初始化数据");
        log.info("请输入IP地址：");
        Scanner scanner = new Scanner(System.in);
        String ip = scanner.next();

        log.info("请输入数据库端口：");
        int port = scanner.nextInt();

        log.info("请输入数据库用户名：");
        String userName = scanner.next();

        log.info("请输入数据库密码：");
        String password = scanner.next();

        log.info("请输入数据库名称：");
        String dbName = scanner.next();

        log.info("信息填写完毕，请核对是否正确，输入y继续：");
        log.info("IP：{}", ip);
        log.info("端口：{}", port);
        log.info("用户名：{}", userName);
        log.info("密码：{}", password);
        log.info("数据库名称：{}", dbName);

        String check = scanner.next();
        if ("y".equals(check)) {
            log.info("该数据库【{}】是否需要新建？是请输入y，否则为n", dbName);
            String next = scanner.next();
            if ("y".equals(next)) {
                createDb(dbName, ip, port, userName, password);
            }
            start(ip, port, userName, password, dbName);
        } else {
            initMysql();
        }
    }


    /**
     * 创建数据库
     */
    private static void createDb(String dbName, String ip, Integer port, String userName, String password) {
        log.info("开始创建新的数据库：{}", dbName);
        String executeSql = "create database if not exists " + dbName.toLowerCase() + " ;";
        String url = "jdbc:mysql://" + ip + ":" + port + "/mysql?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false";
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUsername(userName);
        druidDataSource.setPassword(password);
        druidDataSource.setUrl(url);
        JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource);
        jdbcTemplate.execute(executeSql);
        log.info("数据库:{} 创建完毕", dbName.toLowerCase());
    }

    /**
     * 开始执行sql脚本
     */
    private static void start(String ip, Integer port, String userName, String password, String dbName) {
        long start = System.currentTimeMillis();
        log.info("---------开始加载初始化脚本---------");
        String url = "jdbc:mysql://" + ip + ":" + port + "/" + dbName.toLowerCase() + "?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false";
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUsername(userName);
        druidDataSource.setPassword(password);
        druidDataSource.setUrl(url);
        druidDataSource.setConnectionErrorRetryAttempts(5);
        druidDataSource.setBreakAfterAcquireFailure(true);

        Resource classPathResource = new ClassPathResource("db/" + INIT_DB_FILE_NAME);
        try {
            DruidPooledConnection connection = druidDataSource.getConnection();
            ScriptUtils.executeSqlScript(connection, classPathResource);
            long end = System.currentTimeMillis();
            log.info("初始化脚本执行完毕，耗时: {}s ", (float) (end - start) / 1000);
        } catch (Exception e) {
            log.error("脚本执行异常,{}", e.getMessage());
        }
    }


    private void printLogo() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.info("\r\n━━━━━━神兽出没━━━━━━\n" +
                " * 　　　┏┓　　　┏┓\n" +
                " * 　　┏┛┻━━━┛┻┓\n" +
                " * 　　┃　　　　　　　┃\n" +
                " * 　　┃　　　━　　　┃\n" +
                " * 　　┃　┳┛　┗┳　┃\n" +
                " * 　　┃　　　　　　　┃\n" +
                " * 　　┃　　　┻　　　┃\n" +
                " * 　　┃　　　　　　　┃\n" +
                " * 　　┗━┓　　　┏━┛\n" +
                " * 　　　　┃　　　┃  神兽保佑\n" +
                " * 　　　　┃　　　┃  代码无bug　　\n" +
                " * 　　　　┃　　　┗━━━┓\n" +
                " * 　　　　┃　　　　　　　┣┓\n" +
                " * 　　　　┃　　　　　　　┏┛\n" +
                " * 　　　　┗┓┓┏━┳┓┏┛\n" +
                " * 　　　　　┃┫┫　┃┫┫\n" +
                " * 　　　　　┗┻┛　┗┻┛\n" +
                " * ━━━━━━启动成功,当前时间: {}━━━━━━", format.format(new Date()));
    }
}
